/* ***************************************************************************
 * Tester for exercise 4 in OS.  v2
 *
 * Author : Amit Lavon
 * ***************************************************************************/

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include "fileperf.hh"


/*************
  DEFINITIONS
 *************/

typedef unsigned int uint;
typedef unsigned long int ulong;
typedef struct outputStruct OutputStruct;


/***********
  VARIABLES
 ***********/

OutputStruct os;
std::vector<uint> fileSizes;

uint minBlockSize = 100;
uint maxBlockSize = 10000;
uint intervalBlockSize = 100;

uint pointerSize = 4;
uint maximalSize = 100000000;
char sizesFile[] = "fileSizes.txt";
char outputFileAccess[] = "access.txt";
char outputFileSpace[]  = "space.txt";

int returnValue = 0;


/***********
  FUNCTIONS
 ***********/

static void readFileSizes()
{
	// Clear size vector
	fileSizes.clear();

	// Open file
	FILE* input = fopen(sizesFile, "r");
	if (input == NULL)
	{
		std::cerr << "could not open input file\n";
		return;
	}

	// Read contents
	char buffer[100];
	while (fgets(buffer, sizeof(buffer), input) != NULL)
	{
		uint size = (uint)atoi(buffer);
		fileSizes.push_back(size);
	}

	// Close file
	fclose(input);
}

int main() {

	// Read file sizes
	readFileSizes();
	if (fileSizes.empty()) return 1;

	// Open output files
	FILE* outputAccess = fopen(outputFileAccess, "w");
	FILE* outputSpace = fopen(outputFileSpace, "w");
	if (outputAccess == NULL || outputSpace == NULL)
	{
		std::cerr << "could not open output files\n";
		return 1;
	}

	// Try different block sizes
	OutputStruct osInode;
	OutputStruct osList;
	for (uint blockSize = minBlockSize; blockSize <= maxBlockSize; blockSize += intervalBlockSize)
	{
		std::cerr << "calculating block size " << blockSize << "\n";

		// Calculate stuff
		int resultInode = fileSystemPerformance(blockSize, pointerSize,
				maximalSize, FS_INODE, fileSizes, &osInode);
		int resultList = fileSystemPerformance(blockSize, pointerSize,
				maximalSize, FS_LINKED_LIST, fileSizes, &osList);

		// Check for errors
		if (resultList != 0 || resultInode != 0)
		{
			fprintf(outputAccess, "ERROR\n");
			fprintf(outputSpace, "ERROR\n");
			std::cerr << "error in calculations\n";
			returnValue = 1;
			break;
		}
		else
		{
			fprintf(outputAccess, "%d %f %f\n", blockSize, osList.averageAccessNum, osInode.averageAccessNum);
			fprintf(outputSpace, "%d %ld %ld\n", blockSize, osList.space, osInode.space);
		}
	}

	fclose(outputAccess);
	fclose(outputSpace);

	printf("Saved access results to '%s'\nSaved space results to '%s'\n", outputFileAccess, outputFileSpace);

	return returnValue;
} //*/

